/***************************************************************************
 *   Copyright (C) 2009 by Zheng Yonglei
 *   zhengyonglei@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef __WORDMANAGER_H
#define __WORDMANAGER_H

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include <queue>
#include <cassert>

#include <QCoreApplication>
#include <QDir>
#include <QString>
#include <QSettings>
#include <QVariant>
#include <QVector>

#include "SQLiteDB.h"
#include "StaticModule.h"
#include "DictManager.h"
#include "Logger.h"
#include "Word.h"
//#include "config.h"

#define WM StaticModule<WordManager>::getInstance()

using namespace std;

class AssociateWord
{
public:
	int id;
	int conWeight;
	QString English;

	AssociateWord():id(0),conWeight(0),English(QString()){}
	AssociateWord(int i, int c, QString s):id(i),conWeight(c),English(s){}
	AssociateWord(const AssociateWord& a){id = a.id; conWeight=a.conWeight; English=a.English;}
};

class Word;
class WordManager
{
protected:
	map<int, QString> mAllWordMap;
	map<int, Word> mWordsMap;//map<word id, word pointer>
	QVector<int>mWordsVector;//mWordsVector[index] = word id
	QVector<int>mUnhitReviewingWords;
	QVector<int>mResumeWords;
	QVector<int>mResumeUnhitRevWords;

	QString mPathSeparator;

	int mReviewCycle;
	int mReviewFrequency;

	int mCurWordID;
	int mCurWordIndex;
	int mLastWordID;
	QVector<int> mTestWordHistory;

	WordManagerTask mCurTask;
	QString mCurTaskElapseTime;
	WordStatus mCurCandidatesType;

	int mTotalReciteCount;

	QVector<int> mRecitingWord;
	QVector<int> mReviewingWord;
	QVector<int> mUntouchedWord;
	QVector<int> mFinishedWord;
	//QVector<int> mAssociateWord;

	TestMethod mReciteTestMethod;
	int mCorrectChoiceIndex;
	int mSelectedChoice;

	//QVector<QString> mDictList;
	map<int, QVector<AssociateWord> > mAssociateMap;
	QVector<AssociateWord> mAssociateTempVector;
	int mAssociateRemainCycle;
	QString mAssociateRoot;

public:
	WordManager();
	~WordManager();

	void readSettings();
	void writeSettings();

	//about setting tasks
	void setTask(WordManagerTask task);
	WordManagerTask getTask(){return mCurTask;}
	void setCurTaskElapseTime(QString time){mCurTaskElapseTime = time;}
	QString getCurTaskElapseTime(){return mCurTaskElapseTime;}
	void loadUnfinishedTask();

	void initRecitingTask();
	void initBrowseTask();

	void initActiveWordTotalReciteCount();
	int getActiveWordTotalReciteCount();

	//prepare before do the task
	//void loadAllWordMap();
	void getBasicInfo(int id);
	void getBasicInfoByListName();
	void getBasicInfoByActiveStatus();
	void getBasicInfoByResumeList();
	void addWord(int id);

	void prepareToReciteWords();
	void prepareToBrowseWords();

	//end tasks
	void clearWordContainers();
	void finishLastTask();
	void finishBrowseWords();
	void finishReciteWords();

	//about database
	//bool createConnection();//create a connection to the database
	void resetRecitingInfoOnDatabase();
	//void execQurey(QString queryCommand);

	//for words
	void getCurWordRecitingInfo();
	void updateCurWordRecitingInfo();
	void remember();
	void forget();

	Word* getCurWord();
	Word* getWord(int id);
	Word* getWordByIndex(int index);
	int getCurWordID(){return mCurWordID;}
	void setCurWordId(int id);
	int getCurWordIndex(){return mCurWordIndex;}
	int getCurWordIndexByID(int id){return mWordsVector.indexOf(id);}
	QVector<int>& getTestWordHistory(){return mTestWordHistory;}

	//QVector<QString>& getDictList(){return mDictList;}

	int getListWordCount(){return mWordsMap.size();}

	int getActiveWordCount();
	int getActiveWordTotalFinishedCount();

	int getRecitingWordCount(){return mRecitingWord.size();}
	int getReviewingWordCount(){return mReviewingWord.size();}
	int getUntouchedWordCount(){return mUntouchedWord.size();}
	int getFinishedWordCount(){return mFinishedWord.size();}
	int getUnhitReviewingWordCount(){return mUnhitReviewingWords.size();}
	int getResumeWordCount(){return mResumeWords.size();}
	int getWordCountByStatus(WordStatus status);

	//for word browsing
	void browseWordByIndex(int index);

	//for choosing words to recite
	void updateStatusCount();
	void updateWordFrozenInfo();
	void selectCandidatesType();
	WordStatus getCandidatesType(){return mCurCandidatesType;}
	bool reciteNextWord();
	int selectRecitingWord();
	int getCorrectChoiceIndex(){return mCorrectChoiceIndex;}
	int getSelectedChoice(){return mSelectedChoice;}

	//for recite method
	TestMethod getReciteTestMode();
	void setReciteTestMode();
	void randomSelectWords(vector<int>&words, int count);
	bool checkChoice(int selectedChoice);
	//void randomSelectEnglish();

	//for reviewinging words
	void setReviewFrequency();

	int random(int size);
	bool random(QVector<int>&results , int resultCount, int size, int base = 0);

	//for associate map
	void loadAssiciateMap();
	QStringList getAssociateWords(int id, bool isActive=true);
	QString getAssociateRoot(){return mAssociateRoot;}
};

#endif //__WORDMANAGER_H
